package com.abel.util;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import com.abel.domain.Application;
import com.abel.domain.AuthPrincipal;
import com.abel.domain.DesiredPosition;
import com.abel.domain.Education;
import com.abel.domain.HelpfulInformation;
import com.abel.domain.MilitaryService;
import com.abel.domain.OptionalInformation;
import com.abel.domain.Person;
import com.abel.domain.PersonProfile;
import com.abel.domain.PersonalInformation;
import com.abel.domain.WorkExperience;
import com.abel.domain.types.EducationType;
import com.abel.domain.types.HelpfulInfoStatus;
import com.abel.domain.types.MaritalStatus;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.AcroFields;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;
import com.lowagie.text.pdf.PdfWriter;

public class ApplicationFormGenerator {
	
	
	public void generateApplicationForm(OutputStream outputStream, Person person) {
		
		PdfReader applicationTemplate  = null;
		PdfWriter writer = null;
		PdfStamper stamper = null;
		Document document = new Document();
		try {

			document.open();
	        writer = PdfWriter.getInstance(document, outputStream);
	        applicationTemplate = new PdfReader("C:/works/workspace/AbelWeb/WebContent/ApplicationForm.pdf");
			
	        stamper = new PdfStamper(applicationTemplate, outputStream);
			AcroFields form = stamper.getAcroFields();
			Iterator iterator = form.getFields().keySet().iterator();
			
			while (iterator.hasNext()){
				System.out.println(":" + iterator.next());
			}
			stamper.setFormFlattening(true); 
			this.populateApplicationForm(form, person);
		
		} 
		catch (Exception e) {
			e.printStackTrace();
		}
		finally {

			try {
				
				stamper.close();
				
			} 
			catch (DocumentException e) {
				
				e.printStackTrace();
			} 
			catch (IOException e) {
				
				e.printStackTrace();
			}
			//document.close();
		}
	}
	
	private void populateApplicationForm(AcroFields form, Person person) {
		
		this.populateAuthInformation(form, UserSessionLocator.getUserSession().getAuthPrincipal());
		this.populateApplication(form, person.getApplication());
		
	}
	
	
	private void populateApplication(AcroFields form, Application application) {
		
		try {
			
			form.setField("app_id",Integer.toString(application.getApplicationId()));
			form.setField("appl_date", formatDate(application.getPersonProfile().getPersonalInformation().getLastUpdateDate()));
		} 
		catch (IOException e) {
			e.printStackTrace();
		} 
		catch (DocumentException e) {
			e.printStackTrace();
		}

		this.populatePersonProfile(form, application.getPersonProfile());
		
		if (application.getPersonProfile().getMilitaryServiceInformation() != null) {
			this.populateMilitaryService(form, application.getPersonProfile().getMilitaryServiceInformation());
		}
		
		if (application.getEducation() != null) { 
			this.populateEducation(form, application.getEducation());
		}
		
		if (application.getWorkExperiences() != null) {
		this.populateWorkExperience(form, application.getWorkExperiences());
		}

	}
	
	
	private void populatePersonProfile(AcroFields form, PersonProfile personProfile) {
		
		if (personProfile.getPersonalInformation() != null) {
			this.populatePersonalInformation(form, personProfile.getPersonalInformation());
		}
		if (personProfile.getHelpfulInformation() != null) {
			this.populateHelpfulInformation(form, personProfile.getHelpfulInformation());
		}
		if (personProfile.getOptionalInformation() != null) {
			this.populateOptionalInformation(form, personProfile.getOptionalInformation());
		}
		if (personProfile.getDesiredPosition() != null) {	
			this.populateDesiredPositionInformation(form, personProfile.getDesiredPosition());
		}
	}
	
	
	private void populateAuthInformation(AcroFields form, AuthPrincipal authPrincipal) {

		try {
			
			form.setField("email", formatData(authPrincipal.getEmail()));
		} 
		catch (IOException e) {
			e.printStackTrace();
		} 
		catch (DocumentException e) {
			e.printStackTrace();
		}

	}
	
	private void populatePersonalInformation(AcroFields form, PersonalInformation personalInformation) {
	
		try {
			
			form.setField("address",  formatAddress(personalInformation.getAddressLine1(),
					personalInformation.getAddressLine2(), 
					personalInformation.getCity(), 
					personalInformation.getState(), 
					personalInformation.getZip()));
			form.setField("alternate_phone", formatData(personalInformation.getAlternatePhone()));
			form.setField("home_phone", formatData(personalInformation.getHomePhone()));
			form.setField("business_phone", formatData(personalInformation.getWorkPhone()));
			form.setField("name", formatData(personalInformation.getFirstName()) + 
					" " + formatData(personalInformation.getMiddleName()) +  
					" " + formatData(personalInformation.getLastName()));
			form.setField("Birthdate", formatDate(personalInformation.getDateOfBirth()));
			form.setField("ssn",formatData(personalInformation.getSsn()));
			form.setField("emergency",formatEmergencyInfo(personalInformation.getEmergencyContact(),
					personalInformation.getEmergencyContactRelation(),
					personalInformation.getEmergencyContactPhone()));
			//TODO - is there a business phone on the form
			//TODO - to be populated?
//			form.setField("off_use_1",personalInformation.);
//			form.setField("off_use_2",personalInformation.);
//			form.setField("pc",personalInformation.);
//			form.setField("w_no",personalInformation.);
			

			
			

		} 
		catch (IOException e) {
			e.printStackTrace();
		} 
		catch (DocumentException e) {
			e.printStackTrace();
		}
	}
	
	private void populateOptionalInformation(AcroFields form, OptionalInformation optionalInformation) {

		try {
			
			form.setField("children_ages", formatData(optionalInformation.getChildrensAges()));
			
			if (optionalInformation.getMaritalStatus() != null) {
				
				if (optionalInformation.getMaritalStatus().equalsIgnoreCase(MaritalStatus.DIVORCED.getMaritalStatusCode())) {
					form.setField("divorced_yes","Yes");
					form.setField("divorced_no","Off");
					form.setField("married_no","Yes");
					form.setField("separated_no","Yes");
					form.setField("single_no","Yes");
				}
				if (optionalInformation.getMaritalStatus().equalsIgnoreCase(MaritalStatus.MARRIED.getMaritalStatusCode())) {
					form.setField("married_yes","Yes");
					form.setField("married_no","Off");
					form.setField("divorced_no","Yes");
					form.setField("separated_no","Yes");
					form.setField("single_no","Yes");
				}
				if (optionalInformation.getMaritalStatus().equalsIgnoreCase(MaritalStatus.SEPARATED.getMaritalStatusCode())) {
					form.setField("separated_yes","Yes");
					form.setField("separated_no","Off");
					form.setField("divorced_no","Yes");
					form.setField("married_no","Yes");
					form.setField("single_no","Yes");

				}
				if (optionalInformation.getMaritalStatus().equalsIgnoreCase(MaritalStatus.SINGLE.getMaritalStatusCode())) {
					form.setField("single_yes","Yes");
					form.setField("single_no","Off");
					form.setField("divorced_no","Yes");
					form.setField("married_no","Yes");
					form.setField("separated_no","Yes");
				}
			}
			form.setField("Height", formatData(optionalInformation.getHeight()));
			form.setField("Weight", formatData(optionalInformation.getWeight()));


		} 
		catch (IOException e) {
			e.printStackTrace();
		} 
		catch (DocumentException e) {
			e.printStackTrace();
		}		
	}
	
	private void populateHelpfulInformation(AcroFields form, HelpfulInformation helpfulInformation) {
		try {
			form.setField("car_no", 
					evaluateCheckBox(helpfulInformation.getAccessToCar(), 
							HelpfulInfoStatus.NO.getStatusCode()));
			form.setField("car_yes", 
					evaluateCheckBox(helpfulInformation.getAccessToCar(), 
							HelpfulInfoStatus.YES.getStatusCode()));
			form.setField("employed_no", 
					evaluateCheckBox(helpfulInformation.getEmployed(), 
							HelpfulInfoStatus.NO.getStatusCode()));
			form.setField("employed_yes", 
					evaluateCheckBox(helpfulInformation.getEmployed(), 
							HelpfulInfoStatus.YES.getStatusCode()));
			form.setField("relocate_no", 
					evaluateCheckBox(helpfulInformation.getWillingToRelocate(), 
							HelpfulInfoStatus.NO.getStatusCode()));
			form.setField("relocate_yes", 
					evaluateCheckBox(helpfulInformation.getWillingToRelocate(), 
							HelpfulInfoStatus.YES.getStatusCode()));
			form.setField("travel_no", 
					evaluateCheckBox(helpfulInformation.getWillingToTravel(), 
							HelpfulInfoStatus.NO.getStatusCode()));
			form.setField("travel_yes", 
					evaluateCheckBox(helpfulInformation.getWillingToTravel(), 
							HelpfulInfoStatus.YES.getStatusCode()));
			form.setField("travel_pct",Integer.toString(helpfulInformation.getTravelPercentage()));

			
		} 
		catch (IOException e) {
			e.printStackTrace();
		}
		catch (DocumentException e) {
			e.printStackTrace();
		}		
	}
	
	private void populateDesiredPositionInformation(AcroFields form, DesiredPosition desiredPositions) {
		
		try {
			
			form.setField("desired_pos_1",formatData(desiredPositions.getPosition1stDesired()));
			form.setField("desired_pos_2",formatData(desiredPositions.getPosition2ndDesired()));
			form.setField("least_sal_acceptable",
					desiredPositions.getLeastSalaryAccepted() > 0 ? 
							Double.toString(desiredPositions.getLeastSalaryAccepted()) : "");
			form.setField("sal_desired",
					desiredPositions.getSalaryDesired() > 0 ? 
							Double.toString(desiredPositions.getSalaryDesired()) : "");

			
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		catch (DocumentException e) {
			e.printStackTrace();
		}		
	}
	
	private void populateMilitaryService(AcroFields form, MilitaryService militaryService) {
		try {

			form.setField("dut_spl_training", formatData(militaryService.getMltSplTrainDesc()));
			form.setField("mil_branch", formatData(militaryService.getMltBranch()));
			form.setField("mil_disc_dt", formatDate(militaryService.getMltDischargeDate()));
			form.setField("mil_enter_dt", formatDate(militaryService.getMltInductionDate()));
			form.setField("mil_rank", formatData(militaryService.getMltRank()));
			
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		catch (DocumentException e) {
			e.printStackTrace();
		}		
	}
	
	private void populateEducation(AcroFields form, List<Education> education) {

		try {
			
			Education schoolEducation = null;
			Education collegeEducation = null;
			Education specialEducation = null;
			
			for (Education ed: education) {
				
				if (ed.getEduType().equals(EducationType.HSC.getEducationTypeCode())
						&& schoolEducation == null) {
					
					schoolEducation = ed;
				}
				else if (ed.getEduType().equals(EducationType.COL.getEducationTypeCode())
						&& collegeEducation == null) {
					
					collegeEducation = ed;
				}
				else if (ed.getEduType().equals(EducationType.ADV.getEducationTypeCode())
						&& specialEducation == null) {
					
					specialEducation = ed;
				}
			}
			
			if (collegeEducation != null) {

				form.setField("coll_degree", formatData(collegeEducation.getEduDegree()));
				form.setField("coll_grad_no",
						evaluateCheckBox(collegeEducation.getEduGraduateYn(), 
								HelpfulInfoStatus.NO.getStatusCode()));
				form.setField("coll_grad_yes",
						evaluateCheckBox(collegeEducation.getEduGraduateYn(), 
								HelpfulInfoStatus.YES.getStatusCode()));
				form.setField("coll_major", formatData(collegeEducation.getEduGraduateMajor()));
				form.setField("coll_year", formatData(collegeEducation.getEduGraduateYear()));
				form.setField("college", formatSchoolAddress(collegeEducation.getEduSchoolName(), 
						collegeEducation.getEduSchoolCity(),
						collegeEducation.getEduSchoolState()));
			}
			
			if (schoolEducation != null) {
			
				form.setField("sch_degree", formatData(schoolEducation.getEduDegree()));
				form.setField("sch_grad_no",
						evaluateCheckBox(schoolEducation.getEduGraduateYn(), 
								HelpfulInfoStatus.NO.getStatusCode()));
				form.setField("sch_grad_yes",
						evaluateCheckBox(schoolEducation.getEduGraduateYn(), 
								HelpfulInfoStatus.YES.getStatusCode()));
				form.setField("sch_major", formatData(schoolEducation.getEduGraduateMajor()));
				form.setField("sch_year", formatData(schoolEducation.getEduGraduateYear()));
				form.setField("school", formatSchoolAddress(schoolEducation.getEduSchoolName(), 
						schoolEducation.getEduSchoolCity(),
						schoolEducation.getEduSchoolState()));
			}
			
			if (specialEducation != null) {

				form.setField("spl", formatSchoolAddress(specialEducation.getEduSchoolName(), 
					specialEducation.getEduSchoolCity(),
					specialEducation.getEduSchoolState()));
				form.setField("spl_degree", formatData(specialEducation.getEduDegree()));
				form.setField("spl_grad_no",
						evaluateCheckBox(specialEducation.getEduGraduateYn(), 
								HelpfulInfoStatus.NO.getStatusCode()));
				form.setField("spl_grad_yes",
						evaluateCheckBox(specialEducation.getEduGraduateYn(), 
								HelpfulInfoStatus.YES.getStatusCode()));
				form.setField("spl_major", formatData(specialEducation.getEduGraduateMajor()));
				form.setField("spl_year", formatData(specialEducation.getEduGraduateYear()));
			}
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		catch (DocumentException e) {
			e.printStackTrace();
		}		
	}
	
	private void populateWorkExperience(AcroFields form, List<WorkExperience> workExperiences) {

		try {
			
			int i = 1;
			
			for (WorkExperience workExperience : workExperiences) {

				form.setField("pos_" + i + "_co_addr", formatAddress(workExperience.getWrkAddrLine1(),
						workExperience.getWrkAddrLine2(),
						workExperience.getWrkCity(),
						workExperience.getWrkState(), 
						workExperience.getWrkZip()));
				form.setField("pos_" + i + "_co_bus", formatData(workExperience.getWrkBusinessType()));
				form.setField("pos_" + i + "_co_name", formatData(workExperience.getWrkCompanyName()));
				form.setField("pos_" + i + "_date_from", formatData(workExperience.getWrkStartDate()));
				form.setField("pos_" + i + "_date_to", formatData(workExperience.getWrkEndDate()));
				form.setField("pos_" + i + "_dut_resp", formatData(workExperience.getWrkResponsibility()));
				form.setField("pos_" + i + "_leave_reason", formatData(workExperience.getWrkLeaveReason()));
				form.setField("pos_" + i + "_pay", 
						workExperience.getWrkGrossAnnualPay() > 0 ? 
								Long.toString(workExperience.getWrkGrossAnnualPay()) : "");
				form.setField("pos_" + i + "_position_held", formatData(workExperience.getWrkPosition()));
				form.setField("pos_" + i + "_supervisor", formatData(workExperience.getWrkSupervisorName()));

				i++;
			}
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		catch (DocumentException e) {
			e.printStackTrace();
		}		
	}
	


	
	public static void main(String[] args) {
		
		ApplicationFormGenerator generator = new ApplicationFormGenerator();
		
		String outputFileName = "C:/works/workspace/AbelWeb/WebContent/Application_" + Long.toString(new Date().getTime()) + ".pdf";
		try {

			OutputStream pdfStream = new FileOutputStream(outputFileName);
			generator.generateApplicationForm(pdfStream, new Person());
		
		} 
		catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		
	}
	
	
	private String formatData(String fieldValue) {
		
		return fieldValue != null ? fieldValue.trim() : "";
	}
	
	
	private String formatAddress(String addressLine1, 
			String addressLine2, 
			String city, 
			String state,
			String zip) {
		
		StringBuffer buf = new StringBuffer("");
		buf.append(addressLine1 != null && !addressLine1.trim().equals("") ? addressLine1  : "");
		buf.append(addressLine2 != null && !addressLine2.trim().equals("") ? ", " + addressLine2  : "");
		buf.append(city != null && !city.trim().equals("") ? ", " + city  : "");
		buf.append(state != null && !state.trim().equals("") ? ", " + state  : "");
		buf.append(zip != null && !zip.trim().equals("") ? ", " + zip  : "");
		return buf.toString();
	}


	private String formatSchoolAddress(String schoolName, 
			String city, 
			String state) {
		
		StringBuffer buf = new StringBuffer("");
		buf.append(schoolName != null && !schoolName.trim().equals("") ? schoolName  : "");
		buf.append(city != null && !city.trim().equals("") ? ", " + city  : "");
		buf.append(state != null && !state.trim().equals("") ? ", " + state  : "");
		return buf.toString();
	}
	
	
	private String formatDate(Date date) {
		
		return date != null ? new SimpleDateFormat("MM/dd/yyyy").format(date) : "";
	}
	
	
	private String evaluateCheckBox(String value, String evalStatus) {
		
		return value != null  && value.equalsIgnoreCase(evalStatus) ? "Yes" : "Off";
	}
	
	
	private String formatEmergencyInfo(String contact, String relation, String contactPhone) {
		
		StringBuffer emergencyInfo = new StringBuffer("");
		
		if (contact != null && !contact.trim().equals("")) {
			emergencyInfo.append(contact);
		}
		
		if (relation != null && !relation.trim().equals("")) {
			emergencyInfo.append("(");
			emergencyInfo.append(relation);
			emergencyInfo.append(")");
		}
		
		if (contactPhone != null && !contactPhone.trim().equals("")) {
			emergencyInfo.append(contactPhone);
		}
		return emergencyInfo.toString();
		
	}

}
